package cn.mayaslight.wechat.service;

import java.io.ByteArrayInputStream;
import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.mayaslight.common.cache.SysCfgCache;
import cn.mayaslight.common.exception.HandleException;
import cn.mayaslight.common.springbean.CacheManager;
import cn.mayaslight.common.utils.DataFormat;
import cn.mayaslight.common.utils.ReflectUtils;
import cn.mayaslight.common.utils.XMLConverUtil;
import cn.mayaslight.wechat.api.bean.EventMessage;
import cn.mayaslight.wechat.cache.EventCache;
import cn.mayaslight.wechat.common.WeChatConsts;
import cn.mayaslight.wechat.handler.EventHandler;
import cn.mayaslight.wechat.pojo.WeChatEvent;
import cn.mayaslight.wechat.utils.aes.WXBizMsgCrypt;

/**
 * 回调模式抽象类
 * Create by FengHy on 2017年10月30日.
 */
public abstract class CallbackService {
	
	/** get请求处理方法 */
	protected abstract String get(HttpServletRequest request, HttpServletResponse response, String echostr);
	
	/** post请求处理方法 */
	protected abstract String post(HttpServletRequest request, HttpServletResponse response, EventMessage respEvent);
	
	/** 注入iscp */
	protected boolean iscp(){
		String isqyStr = CacheManager.loadUniqueByKey(SysCfgCache.class, WeChatConsts.CacheKeys.ISQY).getCfgVal();
		return Boolean.parseBoolean(isqyStr);
	}
	
	@SuppressWarnings("unchecked")
	public String callback(HttpServletRequest request, HttpServletResponse response) {
		String method = request.getMethod();
		Map<String, String[]> map = request.getParameterMap();
		String signature, timestamp, nonce, echostr;
		if(iscp()){
			signature = DataFormat.getStringKey(map, "msg_signature");
			timestamp = DataFormat.getStringKey(map, "timestamp");
			nonce = DataFormat.getStringKey(map, "nonce");
			echostr = DataFormat.getStringKey(map, "echostr");
		}else{
			signature = DataFormat.getStringKey(map, "signature");
			timestamp = DataFormat.getStringKey(map, "timestamp");
			nonce = DataFormat.getStringKey(map, "nonce");
			echostr = DataFormat.getStringKey(map, "echostr");
		}
		try {
			WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(CacheManager.loadUniqueByKey(SysCfgCache.class, WeChatConsts.CacheKeys.TOKEN).getCfgVal(), CacheManager.loadUniqueByKey(SysCfgCache.class, WeChatConsts.CacheKeys.ENCODING_AES_KEY).getCfgVal(), CacheManager.loadUniqueByKey(SysCfgCache.class, WeChatConsts.CacheKeys.APPID_KEY).getCfgVal());
			echostr = wxcpt.VerifyURL(signature, timestamp, nonce, echostr);
			if (WeChatConsts.Constants.GET.equalsIgnoreCase(method)) {
				return get(request, response, echostr);
			} else if (WeChatConsts.Constants.POST.equalsIgnoreCase(method)) {
				EventMessage event = XMLConverUtil.convertToObject(EventMessage.class, new ByteArrayInputStream(echostr.getBytes()));
				String eventType = event.getEvent();
				String eventKey = event.getEventKey();
				WeChatEvent weChatEvent = CacheManager.loadUniqueByKey(EventCache.class, eventType + "$$" + eventKey);
				String handlerClassName = weChatEvent.getHandlerClass();
				Class<?> handlerClass = Class.forName(handlerClassName);
				if(handlerClass.getSuperclass() != EventHandler.class){
					throw new HandleException("注册类不是EventHandler的子类！");
				}
				EventHandler handler = (EventHandler) ReflectUtils.newInstance(handlerClass);
				EventMessage respEvent = new EventMessage();
				respEvent.setFromUserName(event.getToUserName());
				respEvent.setToUserName(event.getFromUserName());
				respEvent.setMsgType(weChatEvent.getRespMsgType());
				respEvent.setCreateTime(new Date().getTime());
				respEvent.setContent(handler.handle(event));
				return post(request, response, respEvent);
			}
		} catch (Exception e) {
			throw new HandleException("验证URL失败，错误原因请查看异常：" + e.getMessage());
		}
		throw new HandleException("请求方式不正确!");
	}

}
